#include "gp_dp1_ctl.h"
#include "sock_msg_ctl.h"
#include "gp_layout_map.h"
#include "stdio.h"
#include "string.h"
#include "../lua/action_msg.h"
#include "resource_manage.h"
#include <unistd.h>
#include "gp_dj_ctl.h"

#define SID_DP1_Z 1
#define SID_DP1_JAWZ 22
#define SID_DP1_X 20
#define SID_DP1_Y 21

#ifdef _GP_1
#define SID_DP1_JAW 82
#else
#define SID_DP1_JAW 80
#endif

void dp1ActFunc(void * paramIn,void * actResultOut)
{
    if(!paramIn || !actResultOut)
    {
        return;
    }
    printf("enter in dp1ActFunc\n");
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;
    
    if(pstActMsg->msgHead.actType == ACT_SINGLE_MOVE)
    {
        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_STEPS)
        {
            int component = 0;
            char * pData = (char *)(pstActMsg->paramData);
            memcpy(&component,pData,sizeof(int));

            pData += sizeof(int);

            int steps = 0;
            memcpy(&steps,pData,sizeof(int));

            int sidArr[7] = {SID_DP1_X,SID_DP1_Y,SID_DP1_Z,SID_DP1_JAWZ,SID_DP1_JAW,0,0};
            

            if(component<0 || component>=7)
            {
                actSuccess = 0;
            }
            else if(sidArr[component] == 0)
            {
                actSuccess = 0;
            }

            else
            {
                move_param moveParam;
                moveParam.pos = steps;
                moveParam.speed = 20000;
                moveParam.inc_speed = 80000;
                moveParam.dec_speed = 80000;
                moveParam.sid = sidArr[component];

                if(moveParam.sid == SID_DP1_Z)
                {
                    moveParam.speed = 4500;
                    moveParam.inc_speed = 8000;
                    moveParam.dec_speed = 8000;                    
                }
                actSuccess = uimMoveAct_multi(&moveParam,1,20000);
            }

        }
        else if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_POS)
        {
            location_layout locLayout;
            location_axis locAxis;
            memcpy(&locLayout,((char*)pstActMsg->paramData) + sizeof(int),sizeof(location_layout));
            CGpLayout * pstLayout = CGpLayout::get_instance();
            int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
            if(convertRet)
            {
                printf("convert location failed,errorNum:%d\n",convertRet);
            }
            else 
            {
                printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

            }
            int component = -1;
            memcpy(&component,(char*)pstActMsg->paramData,sizeof(int));
            actSuccess = dp1_single_move_pos(&locAxis,component);
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_PARRAL_MOVE)
    {
        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_POS)
        {
            location_layout locLayout;
            location_axis locAxis;
            memcpy(&locLayout,((char*)pstActMsg->paramData) + sizeof(int),sizeof(location_layout));
            printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
            locLayout.location_type,
            locLayout.indexX,
            locLayout.indexY,
            locLayout.column_x,
            locLayout.row_y);
            CGpLayout * pstLayout = CGpLayout::get_instance();
            int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
            if(convertRet)
            {
                printf("convert location failed,errorNum:%d\n",convertRet);
            }
            else 
            {
                printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
                
                actSuccess = dp1XY_move_beta(&locAxis);
            }
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SINGLE_INIT)
    {
        int component = -1;
        memcpy(&component,(char*)pstActMsg->paramData,sizeof(int));
        printf("dp1ActFunc,single init,componet:%d\n",component);
        actSuccess = dp1_single_init(NULL,component);
    }
    else if(pstActMsg->msgHead.actType == ACT_MODULE_INIT)
    {
        printf("dp1ActFunc,module init\n"); 
        actSuccess = dp1_module_init(NULL);       
    }
    else if(pstActMsg->msgHead.actType == ACT_SUCK_LIQUID)
    {
        printf("dp1ActFunc, suck liquid\n");
        actSuccess = dp1_suck(pstActMsg);
    }
    else if(pstActMsg->msgHead.actType == ACT_SPIT_LIQUID)
    {
        printf("dp1ActFunc, suck liquid\n");
        actSuccess = dp1_spit(pstActMsg);
    }
    else if(pstActMsg->msgHead.actType == ACT_TIP_CTL)
    {
        printf("dp1ActFunc, tip ctl\n");
        if(pstActMsg->msgHead.paramType == PARAM_GET_TIP)
        {
            actSuccess = dp1_gettip(pstActMsg);
        }
        else if(pstActMsg->msgHead.paramType == PARAM_DROP_TIP)
        {
            actSuccess = dp1_droptip(pstActMsg);
        }

    }
    else if(ACT_SPIT_LIQUID_MULTI == pstActMsg->msgHead.actType)
    {
        actSuccess = dp1_spit_multi(pstActMsg);
    }
    else if(ACT_JAW_TRANS == pstActMsg->msgHead.actType)
    {
        actSuccess = dp1_transtube(pstActMsg);
    }
    else if(ACT_PLUNGER_PUMP == pstActMsg->msgHead.actType)
    {
        //printf("ACT_PLUNGER_PUMP,\n");
        if(PARAM_AXIS_MOVE_POS == pstActMsg->msgHead.paramType)
        {
            int component = 0;
            char * ptrData = (char *)pstActMsg->paramData;

            memcpy(&component,ptrData,sizeof(int));
            ptrData += sizeof(int);

            location_layout locLayout;
            memcpy(&locLayout,ptrData,sizeof(location_layout));

            if(component == MT_PUMP)
            {
                int isSuck = 1;
                int suckvolume = locLayout.column_x;
                if(suckvolume < 0)
                {
                    isSuck = 0;
                    suckvolume = 0 - suckvolume;
                }
                actSuccess = dp1_pump_ctl(isSuck, suckvolume);
            }
        }
    }

    msgAckSock * pstResult = (msgAckSock *)actResultOut;

    if(!actSuccess)
    {
        pstResult->status = 1;
    }
    else
    {
        pstResult->status = 0;
    }
}


int dp1XY_move(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    const int sid_dp1_z = 1;
    const int sid_dp1_jawz = 22;
    move_param moveParam[2];
    moveParam[0].sid = sid_dp1_z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 8000;
    moveParam[0].inc_speed = 8000;
    moveParam[0].speed = 4500;
    moveParam[1].sid = sid_dp1_jawz;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    int actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dp1 z and dp1 jawz go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }
    
    const int sid_dp1_x = 20;
    const int sid_dp1_y = 21;
    moveParam[0].sid = sid_dp1_x;
    moveParam[0].pos = pstLocAxis->x;
    moveParam[0].dec_speed = 32000;
    moveParam[0].inc_speed = 32000;
    moveParam[0].speed = 8000;

    moveParam[1].sid = sid_dp1_y;
    moveParam[1].pos = pstLocAxis->y;
    moveParam[1].dec_speed = 64000;
    moveParam[1].inc_speed = 64000;
    moveParam[1].speed = 16000;

    actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    return actSuccess;

}

int dp1XY_move_beta(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    const int sid_dp1_z = 1;
    const int sid_dp1_jawz = 22;
    move_param moveParam[2];
    moveParam[0].sid = sid_dp1_z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 8000;
    moveParam[0].inc_speed = 8000;
    moveParam[0].speed = 4500;
    moveParam[1].sid = sid_dp1_jawz;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    int actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dp1 z and dp1 jawz go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }

    // if(X_SAFE_POS_TUBE >= pstLocAxis->x)
    // {
    //     moveParam[0].pos = pstLocAxis->x;
    // }
    // else
    // {
    //     moveParam[0].pos = X_SAFE_POS_TUBE;
    // }

    moveParam[0].pos = X_SAFE_POS_TUBE;

    moveParam[0].sid = SID_DP1_X;
    moveParam[0].dec_speed = 32000;
    moveParam[0].inc_speed = 32000;
    moveParam[0].speed = 8000;
    actSuccess = uimMoveAct_multi(moveParam, 1, 20000);
    if(actSuccess!=1)
    {
        printf("dp1XY_move_beta, step1 x move failed\n");
        return 0;
    }
    

    moveParam[0].sid = SID_DP1_Y;
    moveParam[0].pos = pstLocAxis->y;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 32000;
    actSuccess = uimMoveAct_multi(moveParam, 1, 20000);

    if(actSuccess!=1)
    {
        printf("dp1XY_move_beta, step2 y move failed\n");
        return 0;
    }

    //if(X_SAFE_POS_TUBE < pstLocAxis->x)
    //{
        moveParam[0].sid = SID_DP1_X;
        moveParam[0].dec_speed = 32000;
        moveParam[0].inc_speed = 32000;
        moveParam[0].speed = 8000;
        moveParam[0].pos = pstLocAxis->x;
        actSuccess = uimMoveAct_multi(moveParam, 1, 20000);
    //}

    return actSuccess;


}

int dp1XY_move_beta_en(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    const int sid_dp1_z = 1;
    const int sid_dp1_jawz = 22;
    move_param moveParam[2];
    moveParam[0].sid = sid_dp1_z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 8000;
    moveParam[0].inc_speed = 8000;
    moveParam[0].speed = 4500;
    moveParam[1].sid = sid_dp1_jawz;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    int actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dp1 z and dp1 jawz go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }

    if(X_SAFE_POS_TUBE >= pstLocAxis->x)
    {
        moveParam[0].pos = pstLocAxis->x;
    }
    else
    {
        moveParam[0].pos = X_SAFE_POS_TUBE;
    }

    moveParam[0].sid = SID_DP1_X;
    moveParam[0].dec_speed = 32000;
    moveParam[0].inc_speed = 32000;
    moveParam[0].speed = 8000;
    actSuccess = uimMoveAct_multi(moveParam, 1, 20000);
    if(actSuccess!=1)
    {
        printf("dp1XY_move_beta, step1 x move failed\n");
        return 0;
    }
    

    moveParam[0].sid = SID_DP1_Y;
    moveParam[0].pos = pstLocAxis->y;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 32000;
    actSuccess = uimMoveAct_multi(moveParam, 1, 20000);

    if(actSuccess!=1)
    {
        printf("dp1XY_move_beta, step2 y move failed\n");
        return 0;
    }

    if(X_SAFE_POS_TUBE < pstLocAxis->x)
    {
        moveParam[0].sid = SID_DP1_X;
        moveParam[0].dec_speed = 32000;
        moveParam[0].inc_speed = 32000;
        moveParam[0].speed = 8000;
        moveParam[0].pos = pstLocAxis->x;
        actSuccess = uimMoveAct_multi(moveParam, 1, 20000);
    }

    return actSuccess;


}

int dp1XY_move_beta_withoutZup(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    const int sid_dp1_z = 1;
    const int sid_dp1_jawz = 22;
    move_param moveParam[2];
    int actSuccess = 0;


    if(X_SAFE_POS_TUBE >= pstLocAxis->x)
    {
        moveParam[0].pos = pstLocAxis->x;
    }
    else
    {
        moveParam[0].pos = X_SAFE_POS_TUBE;
    }

    moveParam[0].sid = SID_DP1_X;
    moveParam[0].dec_speed = 32000;
    moveParam[0].inc_speed = 32000;
    moveParam[0].speed = 8000;
    actSuccess = uimMoveAct_multi(moveParam, 1, 20000);
    if(actSuccess!=1)
    {
        printf("dp1XY_move_beta, step1 x move failed\n");
        return 0;
    }
    

    moveParam[0].sid = SID_DP1_Y;
    moveParam[0].pos = pstLocAxis->y;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 32000;
    actSuccess = uimMoveAct_multi(moveParam, 1, 20000);

    if(actSuccess!=1)
    {
        printf("dp1XY_move_beta, step2 y move failed\n");
        return 0;
    }

    if(X_SAFE_POS_TUBE < pstLocAxis->x)
    {
        moveParam[0].sid = SID_DP1_X;
        moveParam[0].dec_speed = 32000;
        moveParam[0].inc_speed = 32000;
        moveParam[0].speed = 8000;
        moveParam[0].pos = pstLocAxis->x;
        actSuccess = uimMoveAct_multi(moveParam, 1, 20000);
    }

    return actSuccess;


}


int dp1XY_move_withoutZUp(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;

    move_param moveParam[2];

    int  actSuccess = 0;  
    
    const int sid_dp1_x = 20;
    const int sid_dp1_y = 21;
    moveParam[0].sid = sid_dp1_x;
    moveParam[0].pos = pstLocAxis->x;
    moveParam[0].dec_speed = 32000;
    moveParam[0].inc_speed = 32000;
    moveParam[0].speed = 8000;

    moveParam[1].sid = sid_dp1_y;
    moveParam[1].pos = pstLocAxis->y;
    moveParam[1].dec_speed = 64000;
    moveParam[1].inc_speed = 64000;
    moveParam[1].speed = 16000;

    actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    return actSuccess;

}

int dp1_single_move_pos(void * paramIn,int component)
{
    int actSuccess = 1;    
    int sid = -1;
    location_axis * pstLocAxis = (location_axis *)paramIn;
    int pos = 0;

    const int sid_dp1_z = 1;
    const int sid_dp1_jawz = 22;
    switch (component)
    {
        // case MT_AXIS_Z:
        // {
        //     sid = SID_DP1_Z;
        // }
        // break;
        // case MT_JAW_Z:
        // {
        //     sid = SID_DP1_JAWZ;
        // }
        // break;
        case MT_AXIS_X:
        {
            sid = SID_DP1_X;
            pos = pstLocAxis->x;
        }
        break;
        case MT_AXIS_Y:
        {
            sid = SID_DP1_Y;
            pos = pstLocAxis->y;
        }
        break;
        default:
        break;
    }

    if(sid==-1)
    {
        actSuccess = 0;
        printf("in dp1_single_move,param not valid:component:%d\n",component);
        return actSuccess;
    }
    
    if(MT_AXIS_Z!=component && component!=MT_JAW_Z)
    {

        move_param moveParam[2];
        moveParam[0].sid = sid_dp1_z;
        moveParam[0].pos = 0;
        moveParam[0].dec_speed = 8000;
        moveParam[0].inc_speed = 8000;
        moveParam[0].speed = 4500;
        moveParam[1].sid = sid_dp1_jawz;
        moveParam[1].pos = 0;
        moveParam[1].dec_speed = 80000;
        moveParam[1].inc_speed = 80000;
        moveParam[1].speed = 20000;
        actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

        if(actSuccess != 1)
        {
            printf("dp1 z and dp1 jawz go to 0 failed,actRet:%d\n",actSuccess);
            return actSuccess;
        }

    }

    move_param moveParam;

    moveParam.sid = sid;
    moveParam.pos = pos;
    moveParam.dec_speed = 80000;
    moveParam.inc_speed = 80000;
    moveParam.speed = 20000;
    actSuccess = uimMoveAct_multi(&moveParam, 1, 20000);

    

    if(actSuccess != 1)
    {
        printf("dp1 z and dp1 jawz go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }   


}

int adp_reset_init(int liquidDetectTypeIn)
{
    int actsuccess = adpCtl(NULL,TECAN_RESET,20000);

    if(1!=actsuccess)
    {
        return 0;
    }

    tecan_init_param stInitParam;

    stInitParam.detectType = liquidDetectTypeIn;

    return adpCtl(&stInitParam,TECAN_INIT,20000);

}

int dp1_single_init(void * paramIn,int component)
{
    if(MT_PUMP == component)
    {
        return adp_reset_init(0);//0 is for air pressure detecting
    }
    int sid = convertToDp1Sid(component);
    int actSuccess = 0;
    if(sid==-1)
    {
        return actSuccess;
    }

    move_param moveParam;

    moveParam.sid = sid;
    moveParam.pos = 0;
    if(sid==1)
    {//param for adp z
        moveParam.dec_speed = 8000;
        moveParam.inc_speed = 8000;
        moveParam.speed = 4500;
    }
    else
    {
        moveParam.dec_speed = 80000;
        moveParam.inc_speed = 80000;
        moveParam.speed = 20000;        
    }
    
    actSuccess = uimInitAct_multi(&moveParam, 1, 20000);

    return actSuccess;
}
int dp1_module_init(void * paramIn)
{
    move_param moveParam[3];
    moveParam[0].sid = SID_DP1_Z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 8000;
    moveParam[0].inc_speed = 8000;
    moveParam[0].speed = 4500;
    moveParam[1].sid = SID_DP1_JAWZ;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    int actSuccess = uimInitAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dp1 z and dp1 jawz go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }

    moveParam[0].sid = SID_DP1_JAW;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;
    moveParam[1].sid = SID_DP1_X;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 32000;
    moveParam[1].inc_speed = 32000;
    moveParam[1].speed = 4000;

    actSuccess = uimInitAct_multi(moveParam, 2, 20000);

    if(actSuccess != 1)
    {
        printf("dp1 jaw, x init,actRet:%d\n",actSuccess);
        return 0;
        
    }

    moveParam[0].sid = SID_DP1_Y;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 32000;
    moveParam[0].inc_speed = 32000;
    moveParam[0].speed = 8000;
    actSuccess = uimInitAct_multi(moveParam, 1, 20000);

    if(actSuccess != 1)
    {
        printf("dp1 y init,actRet:%d\n",actSuccess);
        return 0;
        
    }
    return actSuccess; 

}

int convertToDp1Sid(int componentIn)
{
    int sid = -1;
    switch (componentIn)
    {
        case MT_AXIS_Z:
        {
            sid = SID_DP1_Z;
        }
        break;
        case MT_JAW_Z:
        {
            sid = SID_DP1_JAWZ;
        }
        break;
        case MT_AXIS_X:
        {
            sid = SID_DP1_X;
        }
        break;
        case MT_AXIS_Y:
        {
            sid = SID_DP1_Y;
        }
        break;
        case MT_JAW:
        {
            sid = SID_DP1_JAW;
        }
        break;
        default:
        break;
    }
    return sid; 
}

const suck_ctl dp1SuckCtlParam[VISCOSITY_DUMMY] = 
{
    {
       .air1 = 5,
       .air2 = 5,
       .speedSuck = 100,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 75*40,//400 ul/s * 4000inc/1000ul
    },
    {
       .air1 = 6,
       .air2 = 6,
       .speedSuck = 90,
       .liquidMore = 12,
       .spitQuan = 5,
       .spitSpeed = 75*40,
    },
    {
       .air1 = 7,
       .air2 = 7,
       .speedSuck = 80,
       .liquidMore = 12,
       .spitQuan = 5,
       .spitSpeed = 75*40,
    }
};

const float z_steps_per_mm = 10.4987;//0.09525mm/step

void adjustZPos_Dp1(dynamic_z* z_height_posIn)
{
    CResource_Manage  * pstResManage = getResourceManage();
    
    int tipType = TIP_1000UL;
    if(pstResManage)
    {
        tipType = pstResManage->get_curr_tip_type( MODULE_DP1); 
    }

    if(tipType==TIP_200UL)
    {
        z_height_posIn->z_tube_mouth += 390;
        z_height_posIn->z_max += 390; 
    }
    else if(tipType==TIP_50UL)
    {
        z_height_posIn->z_tube_mouth += 390;
        z_height_posIn->z_max += 390;
    }
}

void adjustZPos_Dp1_en(dynamic_z* z_height_posIn,int tipTypeIn)
{

    
    int tipType = tipTypeIn;

    if(tipType==TIP_200UL)
    {
        z_height_posIn->z_tube_mouth += 390;
        z_height_posIn->z_max += 390; 
    }
    else if(tipType==TIP_50UL)
    {
        z_height_posIn->z_tube_mouth += 390;
        z_height_posIn->z_max += 390;
    }
}

int dp1_suck(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        actSuccess = dp1XY_move_beta(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp1_suck, x,y go to target location failed\n");
        return 0;
    }
    int liquidType = VISCOSITY_LOW;
    int suckVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|liquidtype|suckVolume|isformulti|remainVolume|tiptype
    memcpy(&liquidType,pstDataBuff,sizeof(int));

    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
       pstResManage->set_curr_liquid_type( DP1_LIQUID_TYPE,liquidType); 
    }

    pstDataBuff += sizeof(int);
    memcpy(&suckVolume,pstDataBuff,sizeof(int));
    
    pstDataBuff += sizeof(int);
    int isForMulti = 0;
    memcpy(&isForMulti,pstDataBuff,sizeof(int));


    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int volumeAir2 = dp1SuckCtlParam[liquidType].air2;
    float volumeAir1 = dp1SuckCtlParam[liquidType].air1;
    int liquidMore = dp1SuckCtlParam[liquidType].liquidMore;
    int volumeSpitBack = dp1SuckCtlParam[liquidType].spitQuan;
    if(isForMulti)
    {
        volumeAir2 = 0;
        volumeAir1 = 10;
        liquidMore = 7;
        volumeSpitBack = 0;

    }
    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,suckVolume,isForMulti);


    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }
    
    //cross the remain volume, then tiptype
    pstDataBuff += (sizeof(int)<<1);
    
    int tipType = TIP_1000UL;   
    memcpy(&tipType,pstDataBuff,sizeof(int));
    printf("in dp1_suck, tip type is %d\n",tipType);

    adjustZPos_Dp1_en(&z_height_pos,tipType);
    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);

    int posPre = z_height_pos.z_tube_mouth;

    suck_param suckParam = {
        .posPre = posPre, // this should be change according to the ----
        .speedPre = 4500, // the speed go to previous position
        .air1Quan = volumeAir1, // the air quantity before suck liquid
        .speedDetect = 210,//20mm/s / 0.009525 = 209.973// the speed of detecting liquid face
        .threshold = 9, // the threshold of detecting
        .stepBelow = 10,// the step continue to go after detecting success
        .speedSuck = dp1SuckCtlParam[liquidType].speedSuck,// the suck speed
        .quantity = suckVolume, // the suck quantity
        .more = liquidMore, // the reduntant quantity
        .posMax = z_height_pos.z_max, //the max pos to go if no liquid ----this should be changed.
        .posPost = posPre, // the position after sucking finished--- this should equals to posPre 
        .speedPost = 105, // the speed to go to posPost,---equals to speedDetect
        .air2Quan = volumeAir2, // the air quantity after suck liquid    
        .spitQuan = volumeSpitBack, // spit back quantity
        .speedSuckAir1 = 50,//ul/s
        .delayAfterSuck = 1000, //ms
        .delayAfterSpit = 500, //ms
        .speedSuckAir2 = 50,//ul/s
        .spitSpeed = dp1SuckCtlParam[liquidType].spitSpeed,//inc/s
    };


    actSuccess = adpCtl(&suckParam,TECAN_SUCK_P, 100000);

    printf("dp1 suck end, go up to 0 now\n");

    move_param stAdpZMove;
    stAdpZMove.pos = 0; //TECAN_Z_MOVE
    stAdpZMove.dec_speed = 8000;
    stAdpZMove.inc_speed = 8000;
    stAdpZMove.speed = 4500;

    actSuccess = adpCtl(&stAdpZMove,TECAN_Z_MOVE, 10000);

    return actSuccess;
}

int dp1_get_container_type(int locTypeIn)
{
    int ret = -1;

    switch(locTypeIn)
    {
       case DP1_OPENLID_SUCK:
       {
           ret = CONTAINER_TUBE_SAMPLE;
       }
       break;
       case DP1_8HOLES_SPIT_BUFF:
       {
           ret = CONTAINER_8TUBE;
       }
       break;

       default:
        break;
    }
    return ret;
}

int dp1_spit(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;
    printf("enter in dp1_spit\n");
    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        actSuccess = dp1XY_move_beta(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp1_spit, x,y go to target location failed\n");
        return 0;
    }

    int liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume|tiptype
    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
       liquidType = pstResManage->get_curr_liquid_type( DP1_LIQUID_TYPE); 
    }
    //memcpy(&liquidType,pstDataBuff,sizeof(int));

    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));
    
    int isFormulti = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isFormulti,pstDataBuff,sizeof(int));
    

    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_spit, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int remainVolume = 0;//-----this should be dynamically calculated.
    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));

    int tipType = TIP_1000UL;
    pstDataBuff += sizeof(int);
    memcpy(&tipType,pstDataBuff,sizeof(int));


    printf("in dp1_spit,liquidType:%d,volume:%d,remain:%d\n",liquidType,spitVolume,remainVolume);
    // float deltaHeightToAdd = 0;
    // int retHeight = volumeToHeight(spitVolume, TUBE_BOTTOM_SEMISPHERE, &deltaHeightToAdd);
    
    // if(retHeight)
    // {
    //     printf("delta height is not valid\n");
    //     return 0;
    // }

    float heightAfterSpit = 0;

    int containerTypeDp1 = dp1_get_container_type(locLayout.location_type);
    
    if(containerTypeDp1 == -1)
    {
        printf("in dp1_spit, get container type failed\n");
        return 0;
    }
    else
    {
        printf("containerType:%d\n",containerTypeDp1);
    }
    

    int converHRet = volumeToHeight_en(remainVolume + spitVolume,containerTypeDp1,&heightAfterSpit);
    if(converHRet != 0)
    {
        printf("in dp1_spit, calc height through remainvolume failed\n");
        return 0;
    }

    // int retHeight = volumeToHeight(remainVolume + spitVolume, TUBE_BOTTOM_SEMISPHERE, &heightAfterSpit);
    // if(retHeight)
    // {
    //     printf("remain height is not valid\n");
    //     return 0;
    // }

    int deltaSteps = (int)(z_steps_per_mm*heightAfterSpit);
    
    //get z max and tube mouth
    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid||((z_height_pos.z_max - z_height_pos.z_tube_mouth)<=0))
    {
        printf("z location is not valid\n");
        return 0;
    }

    if(deltaSteps > (z_height_pos.z_max - z_height_pos.z_tube_mouth))
    {
        printf("delta z is not valid\n");
        return 0;
    }

    adjustZPos_Dp1_en(&z_height_pos,tipType);

    printf("spit z_max:%d,z tube mouth:%d\n",z_height_pos.z_max,z_height_pos.z_tube_mouth);
    
    int posPre = z_height_pos.z_max - deltaSteps;

    printf("deltaSteps:%d,z_max:%d,heightAfterSpit:%d\n",deltaSteps,z_height_pos.z_max,heightAfterSpit);
    printf("spitVolume:%d,air2:%f\n",spitVolume,dp1SuckCtlParam[liquidType].air2);
    tecan_liquid_param spitParam = {
        .posPre = posPre,
        .posPost = z_height_pos.z_tube_mouth,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = 5,
        .speed = (400*40),//400 ul/s * 40000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(20*z_steps_per_mm), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    actSuccess = adpCtl(&spitParam,TECAN_SPIT, 40000);

    printf("dp1 spit end, go up to 0 now\n");

    move_param stAdpZMove;
    stAdpZMove.pos = 0; //TECAN_Z_MOVE
    stAdpZMove.dec_speed = 8000;
    stAdpZMove.inc_speed = 8000;
    stAdpZMove.speed = 4500;

    actSuccess = adpCtl(&stAdpZMove,TECAN_Z_MOVE, 10000);

    return actSuccess;    
    
}

int dp1_spit_multi(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    int volumeCompensate[2] = {-1,1};

    printf("enter in dp1_spit_multi\n");

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        actSuccess = dp1XY_move_beta(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp1_spit_multi, x,y go to target location failed\n");
        return 0;
    }
    //calc the z height
    int liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume|tiptype
    //memcpy(&liquidType,pstDataBuff,sizeof(int));

    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));


    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
       liquidType = pstResManage->get_curr_liquid_type( DP1_LIQUID_TYPE); 
    }

    printf("liquidType:%d,volume:%d\n",liquidType,spitVolume);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_spit_multi, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int isformulti = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isformulti,pstDataBuff,sizeof(int));    

    int remainVolume = 0;//-----this should be dynamically calculated.
    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));      
    // float deltaHeightToAdd = 0;
    // int retHeight = volumeToHeight(spitVolume, TUBE_BOTTOM_SEMISPHERE, &deltaHeightToAdd);
    
    // if(retHeight)
    // {
    //     printf("delta height is not valid\n");
    //     return 0;
    // }

    float heightAfterSpit = 0;

    printf("in dp1_spit_multi,remain:%d,spitVolume:%d\n",remainVolume,spitVolume);

    int retHeight = volumeToHeight_en(remainVolume + spitVolume, CONTAINER_8TUBE, &heightAfterSpit);
    if(retHeight)
    {
        printf("remain height is not valid\n");
        return 0;
    }

    int deltaSteps = (int)(z_steps_per_mm*heightAfterSpit);
    
    //get z max and tube mouth
    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid||((z_height_pos.z_max - z_height_pos.z_tube_mouth)<=0))
    {
        printf("z location is not valid\n");
        return 0;
    }

    if(deltaSteps > (z_height_pos.z_max - z_height_pos.z_tube_mouth))
    {
        printf("delta z is not valid\n");
        return 0;
    }

    int tipType = TIP_1000UL; 
    pstDataBuff += sizeof(int);
    memcpy(&tipType,pstDataBuff,sizeof(int));     

    adjustZPos_Dp1_en(&z_height_pos,tipType);

    //printf("spit z_max:%d,z tube mouth:%d\n",z_height_pos.z_max,z_height_pos.z_tube_mouth);
    
    int posPre = z_height_pos.z_max - deltaSteps;

    printf("spit z_max:%d,z tube mouth:%d,posSpit:%d\n",z_height_pos.z_max,z_height_pos.z_tube_mouth,posPre);

    tecan_liquid_param spitParam = {
        .posPre = posPre,
        .posPost = z_height_pos.z_tube_mouth - 50,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = 0,//dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = 0,
        .speed = (75*40),//400 ul/s * 4000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(20*z_steps_per_mm), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    actSuccess = adpCtl(&spitParam,TECAN_SPIT, 40000);

    if(!actSuccess)
    {
        return actSuccess;
    }
    
    int lenPre = sizeof(location_layout) + 4*sizeof(int);
    int holesNum = (pstActMsg->msgHead.paramLen - lenPre)/sizeof(int) + 1;
    printf("paramLen=%d,numHoles:%d\n",pstActMsg->msgHead.paramLen,
    holesNum);
    signed char* pstSpitHoles = ((signed char *)(pstActMsg->paramData)+lenPre);
    unsigned short volume1 = 0;

    signed char deltax = 0;
    signed char deltay = 0;
    location_layout locLayoutTmp;
    memcpy(&locLayoutTmp,&locLayout,sizeof(location_layout));
    float volumeSuckBack = 0;
    for(int i=1;i<holesNum;i++)
    {
        memcpy(&volume1,pstSpitHoles+2,sizeof(short));
        deltax = *pstSpitHoles;
        deltay = *(pstSpitHoles+1);
        printf("deltax:%d,deltay:%d,volume:%d\n",deltax,deltay,volume1);
        pstSpitHoles+=4;
        //sleep(1);

        locLayoutTmp.column_x =  locLayout.column_x + deltax;
        locLayoutTmp.row_y = locLayout.row_y + deltay; 

        convertRet = pstLayout->convertToAxisLoc(&locLayoutTmp,&locAxis);
        if(convertRet)
        {
            printf("convert location failed,errorNum:%d\n",convertRet);
        }
        else 
        {
            printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
            
            actSuccess = dp1XY_move_withoutZUp(&locAxis);
        }

        if(!actSuccess)
        {
            printf("i=%d,xy move failed\n",i);
            return actSuccess;
        }

        spitVolume = volume1;
        
        if(i == (holesNum-1))
        {
            volumeSuckBack = 5;
            spitVolume = volume1 + volumeCompensate[1];
        }
        printf("spit z_max:%d,z tube mouth:%d,posSpit:%d\n",z_height_pos.z_max,z_height_pos.z_tube_mouth,posPre);
        tecan_liquid_param spitParam = {
        .posPre = posPre,
        .posPost = z_height_pos.z_tube_mouth - 50,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = 0,//dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = volumeSuckBack,
        .speed = (75*40),//400 ul/s * 4000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(20*z_steps_per_mm), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
        };

        actSuccess = adpCtl(&spitParam,TECAN_SPIT, 40000);

        if(!actSuccess)
        {
            printf("i=%d,spit failed\n",i);
            break;
        }        
    }

    move_param stAdpZMove;
    stAdpZMove.pos = 0; //TECAN_Z_MOVE
    stAdpZMove.dec_speed = 8000;
    stAdpZMove.inc_speed = 8000;
    stAdpZMove.speed = 4500;

    actSuccess = adpCtl(&stAdpZMove,TECAN_Z_MOVE, 10000);

    return actSuccess;
}

int dp1_gettip(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        //actSuccess = dp1XY_move(&locAxis);
        actSuccess = dp1XY_move_beta(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp1_gettip, x,y go to target location failed\n");
        return 0;
    }
    int tipType = TIP_1000UL;

    memcpy(&tipType,((char*)pstActMsg->paramData)+sizeof(location_layout),sizeof(int));
    //CGpLayout * pstLayout = CGpLayout::get_instance();
    
    if(locLayout.location_type == DP1_TIPS_INTER_REF)
    {
        tipType = TIP_200UL;
    }
    else
    {
        tipType = TIP_1000UL;
    }    

    // CResource_Manage  * pstResManage = getResourceManage();

    // if(pstResManage)
    // {
    //    pstResManage->set_curr_tip_type( MODULE_DP1,tipType); 
    // }

    dynamic_z zHeightPos;
    int getZRet = pstLayout->getZloc(locLayout.location_type,&zHeightPos);
    if(!getZRet)
    {
        printf("in dp1_gettip,get z log failed\n");
        return 0;
    }
    tecan_tip_param pstTipParam = {
           .posTip = zHeightPos.z_tube_mouth,
           .posRet = 0,
           .speed = 4500
    };

    actSuccess = adpCtl(&pstTipParam,TECAN_LOAD_TIP, 10000);
    
    //goto openlid suck position
    location_layout locOpenlid;
    memset(&locOpenlid,0,sizeof(location_layout));
    locOpenlid.location_type = DP1_OPENLID_SUCK;


    convertRet = pstLayout->convertToAxisLoc(&locOpenlid,&locAxis);
    if(convertRet)
    {
        printf("convert openlid suck location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        //actSuccess = dp1XY_move(&locAxis);
        actSuccess = dp1XY_move_beta(&locAxis);
    }

    return actSuccess;
}

void * thread_open_waste_door(void * paramIn)
{
    door_move * pstDoorMove =  (door_move *)paramIn;

    int arrSteps[EN_WASTE_MAX_POS_NUM] = {260000,370000,380000,200000,200000,100,325000};

    move_param moveParam;
    memset(&moveParam,0,sizeof(move_param));

    moveParam.sid = SID_WASTE_DOOR;

    moveParam.speed = 40000;
    moveParam.inc_speed = 160000;
    moveParam.dec_speed = 160000;
    moveParam.pos = arrSteps[pstDoorMove->doorPos];


    pstDoorMove->result = uimMoveAct_multi(&moveParam,1,200000);

}

int dp1_droptip(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        door_move stDoorMove;
        stDoorMove.result = 0;
        stDoorMove.doorPos = EN_WASTE_DOOR_DROPTIP1;
        pthread_t doorMoveHandle;
        pthread_create(&doorMoveHandle,NULL,thread_open_waste_door,&stDoorMove);
        
        actSuccess = dp1XY_move_beta(&locAxis);

        pthread_join(doorMoveHandle,NULL);

        if(stDoorMove.result != 1)
        {
            printf("in dp1_droptip, door move failed\n");
            return 0; 
        }
    }
    
    if(actSuccess!=1)
    {
        printf("in dp1_droptip, x,y go to target location failed\n");
        return 0;
    }
    //CGpLayout * pstLayout = CGpLayout::get_instance();
    
    dynamic_z zHeightPos;
    int getZRet = pstLayout->getZloc(DP1_DROPTIP,&zHeightPos);
    if(!getZRet)
    {
        printf("in dp1_droptip,get z log failed\n");
        return 0;
    }
    tecan_tip_param pstTipParam = {
           .posTip = zHeightPos.z_tube_mouth,
           .posRet = 0,
           .speed = 4500
    };

    actSuccess = adpCtl(&pstTipParam,TECAN_DROP_TIP, 10000);

    if(actSuccess!=1)
    {
        printf("in dp1_droptip, adp drop tip failed\n");
        return 0;
    }

    move_param moveParam;
    memset(&moveParam,0,sizeof(move_param));

    moveParam.sid = SID_WASTE_DOOR;
    moveParam.speed = 40000;
    moveParam.inc_speed = 160000;
    moveParam.dec_speed = 160000;
    moveParam.pos = WASTE_DOOR_CLOSE_POS;

    actSuccess = uimMoveAct_multi(&moveParam,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp1_droptip, close waste door failed\n");
        return 0;
    }

    location_layout locWait;
    memset(&locWait,0,sizeof(location_layout));

    locWait.location_type = DP1_OPENLID_SUCK;

    convertRet = pstLayout->convertToAxisLoc(&locWait,&locAxis);
    if(convertRet)
    {
        printf("convert wait location failed,errorNum:%d\n",convertRet);
        return 0;
    }

    printf("in dp1_droptip, go to wait, x=%d,y=%d\n",locAxis.x,locAxis.y);

    actSuccess = dp1XY_move_beta(&locAxis);

    if(actSuccess!=1)
    {
        printf("in dp1_droptip, go to wait pos failed\n");
        return 0;
    }

    return actSuccess;
}


int dp1_transtube(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to src location
    location_layout locSrcLayout;
    location_axis locAxis;

    move_param moveParam;
    memset(&moveParam,0,sizeof(move_param));

    // location_axis xSafe;
    // xSafe.x = 20150;
    int posZUpDuringTrans = 2000;
    
    memcpy(&locSrcLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("dp1_transtube, src location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locSrcLayout.location_type,
    locSrcLayout.indexX,
    locSrcLayout.indexY,
    locSrcLayout.column_x,
    locSrcLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    dynamic_z zHeightPos;
    int zSrcHeight = 0;
    int getZRet = 0;
    int convertRet = 0;

    int isDjPMove = 0;
    
    if(locSrcLayout.location_type != 0xffff)
    {
        if(locSrcLayout.location_type == DP1_OPENLID_SUCK)
        {
            locSrcLayout.location_type = DP1_OPENLID_JAW;
        }

        if(locSrcLayout.location_type == DP1_8HOLES_SPIT_A)
        {
            locSrcLayout.location_type = DP1_8HOLES_JAW_A;
            posZUpDuringTrans = JAWZ_TUBE8_TRANS;
        }

        if(locSrcLayout.location_type == DP1_8HOLES_SPIT_B)
        {
            locSrcLayout.location_type = DP1_8HOLES_JAW_B;
            posZUpDuringTrans = JAWZ_TUBE8_TRANS;
        }

        if(locSrcLayout.location_type == DP1_8HOLES_SPIT_BUFF)
        {
            locSrcLayout.location_type = DP1_8HOLES_BUFF_JAW;
            posZUpDuringTrans = JAWZ_TUBE8_TRANS;
        }

        if(locSrcLayout.location_type == DP1_8HOLES_SHAKE_TIP)
        {
            locSrcLayout.location_type = DP1_TUBE8_SHAKE_JAW;            
        }

        if(locSrcLayout.location_type == DP1_TUBE8_SHAKE_JAW)
        {
            posZUpDuringTrans = JAWZ_TUBE8_TRANS;
        }

        convertRet = pstLayout->convertToAxisLoc(&locSrcLayout,&locAxis);
        if(convertRet)
        {
            printf("dp1_transtube, convert dst location failed,errorNum:%d\n",convertRet);
        }
        else 
        {
            if(locSrcLayout.location_type == DP1_TUBE_JAW && 
            locSrcLayout.indexY >= NUM_SAMPLE)
            {
                locAxis.y += DELTA_Y_JAW_REF;
            }
            printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

            if(locSrcLayout.location_type == DP1_REAGENT_JAW
              ||locSrcLayout.location_type == DP1_MAG_SHAKE_JAW)
            {
                isDjPMove = 1;
                location_axis locDjpTomove;
                locDjpTomove.x = 0;
                locDjpTomove.y = 13500;
                actSuccess = djXY_Move(&locDjpTomove,1);

                if(actSuccess != 1)
                {
                    printf("in dp1_transtube, magnet trans, dj go to safe pos failed\n");
                    return 0;
                }
            }

            actSuccess = dp1XY_move_beta(&locAxis);
        }
        
        if(actSuccess!=1)
        {
            printf("in dp1_transtube, x to target location failed\n");
            return 0;
        }

        //2, jaw z go down

        getZRet = pstLayout->getZloc(locSrcLayout.location_type,&zHeightPos);

        if(!getZRet)
        {
            printf("in dp1_transtube, get jawz down location failed\n");
            return 0;       
        }

        zSrcHeight = zHeightPos.z_tube_mouth;
        if(locSrcLayout.location_type == DP1_TUBE_JAW && 
        locSrcLayout.indexY >= NUM_SAMPLE)
        {
            zSrcHeight += DELTA_Z_JAW_REF;
        }
        printf("src z go down to %d\n",zSrcHeight);
        moveParam.pos = zSrcHeight;
        moveParam.dec_speed = 120000;
        moveParam.inc_speed = 120000;
        moveParam.speed = 32000;

        moveParam.sid = SID_DP1_JAWZ;

        actSuccess = uimMoveAct_multi(&moveParam,1,20000);

        if(actSuccess!=1)
        {
            printf("in dp1_transtube, jawz go down failed\n");
            return 0;
        }

        //3, jaw close
        moveParam.pos = DP1_JAW_CLOSE_POS;
        moveParam.dec_speed = 4000;
        moveParam.inc_speed = 4000;
        moveParam.speed = 4000;

        moveParam.sid = SID_DP1_JAW;

        printf("in dp1_transtube, jaw close,pos:%d\n",DP1_JAW_CLOSE_POS);

        actSuccess = uimMoveAct_multi(&moveParam,1,20000);

        if(actSuccess!=1)
        {
            printf("in dp1_transtube, jaw close failed\n");
            return 0;
        }

        //4, jawz go up
        moveParam.pos = posZUpDuringTrans;
        moveParam.dec_speed = 120000;
        moveParam.inc_speed = 120000;
        moveParam.speed = 32000;

        moveParam.sid = SID_DP1_JAWZ;

        actSuccess = uimMoveAct_multi(&moveParam,1,20000);

        if(actSuccess!=1)
        {
            printf("in dp1_transtube, jawz go up failed\n");
            return 0;
        }
    }
    else
    {
        //z go up or do nothing here
    }
    
    //5, x,y go to target pos
    location_layout locDstLayout;

    char * pParam = (char *)pstActMsg->paramData;

    pParam += sizeof(location_layout);

    memcpy(&locDstLayout,pParam,sizeof(location_layout));

    printf("dst location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locDstLayout.location_type,
    locDstLayout.indexX,
    locDstLayout.indexY,
    locDstLayout.column_x,
    locDstLayout.row_y);

    if(locDstLayout.location_type == 0xffff)
    {
        return actSuccess;
    }

    if(locDstLayout.location_type == DP1_OPENLID_SUCK)
    {
        locDstLayout.location_type = DP1_OPENLID_JAW;
    }

    if(locDstLayout.location_type == DP1_8HOLES_SPIT_A)
    {
        locDstLayout.location_type = DP1_8HOLES_JAW_A;
    }

    if(locDstLayout.location_type == DP1_8HOLES_SPIT_B)
    {
        locDstLayout.location_type = DP1_8HOLES_JAW_B;
    }

    if(locDstLayout.location_type == DP1_8HOLES_SPIT_BUFF)
    {
        locDstLayout.location_type = DP1_8HOLES_BUFF_JAW;
    }

    if(locDstLayout.location_type == DP1_8HOLES_SHAKE_TIP)
    {
        locDstLayout.location_type = DP1_TUBE8_SHAKE_JAW;
    }

    if(DP1_DROPTIP == locDstLayout.location_type)
    {
        locDstLayout.location_type = DP1_DROPTUBE;
    }
    int needOpenDoor = 0;

    convertRet = pstLayout->convertToAxisLoc(&locDstLayout,&locAxis);
    if(convertRet)
    {
        printf("dp1_transtube, convert dst location failed,errorNum:%d\n",convertRet);
        return 0;
    }
    else 
    {
        if(locDstLayout.location_type == DP1_TUBE_JAW && 
        locDstLayout.indexY >= NUM_SAMPLE)
        {
            locAxis.y += DELTA_Y_JAW_REF;
        }

        if((locDstLayout.location_type == DP1_REAGENT_JAW
            ||locDstLayout.location_type == DP1_MAG_SHAKE_JAW)
            && isDjPMove == 0)
        {
            isDjPMove = 1;
            location_axis locDjpTomove;
            locDjpTomove.x = 0;
            locDjpTomove.y = 13500;
            actSuccess = djXY_Move(&locDjpTomove,1);

            if(actSuccess != 1)
            {
                printf("in dp1_transtube, magnet trans, dj go to safe pos failed\n");
                return 0;
            }
        }
        printf("dp1_transtube dst loc, x=%d,y=%d\n",locAxis.x,locAxis.y);
        // //4.1, x goto safe position
        // actSuccess = dp1_single_move_pos(&xSafe,MT_AXIS_X);
        // if(actSuccess!=1)
        // {
        //     printf("in dp1_transtube, ds x go to safe location failed\n");
        //     return 0;
        // }
        // //4.2 y goto target positon
        // actSuccess = dp1_single_move_pos(&locAxis,MT_AXIS_Y);
        // if(actSuccess!=1)
        // {
        //     printf("in dp1_transtube, dst y go to target location failed\n");
        //     return 0;
        // }
        // //4.3 x goto dst position
        // actSuccess = dp1_single_move_pos(&locAxis,MT_AXIS_X);
        //int needOpenDoor = 0;
        pthread_t doorMoveHandle;
        door_move stDoorMove;
        if(locDstLayout.location_type == DP1_DROPTUBE 
        || locDstLayout.location_type == DP1_DROPTIP)
        {
            needOpenDoor = 1;
            
        }

        if(needOpenDoor)
        {
            //open the waste door here
            stDoorMove.result = 0;
            stDoorMove.doorPos = EN_WASTE_DOOR_TUBE8;            
            pthread_create(&doorMoveHandle,NULL,thread_open_waste_door,&stDoorMove);
        }


        actSuccess = dp1XY_move_beta_withoutZup(&locAxis);

        if(needOpenDoor)
        {
            pthread_join(doorMoveHandle,NULL);

            if(stDoorMove.result != 1)
            {
                printf("open door for drop tube8 failed\n");
                return 0;
            }
        }

        
    }

    if(actSuccess!=1)
    {
        printf("in dp1_transtube, x,y go to target location failed\n");
        return 0;
    }

    //6, jawz go down
    getZRet = pstLayout->getZloc(locDstLayout.location_type,&zHeightPos);

    if(!getZRet)
    {
        printf("in dp1_transtube, get jawz down location failed\n");
        return 0;       
    }

    int zDesHeight = zHeightPos.z_tube_mouth;
    if(locDstLayout.location_type == DP1_TUBE_JAW && 
    locDstLayout.indexY >= 25)
    {
        zDesHeight += DELTA_Z_JAW_REF;
    }

    printf("dst z go down to %d\n",zDesHeight);

    moveParam.pos = zDesHeight;
    moveParam.dec_speed = 120000;
    moveParam.inc_speed = 120000;
    moveParam.speed = 32000;

    moveParam.sid = SID_DP1_JAWZ;

    actSuccess = uimMoveAct_multi(&moveParam,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp1_transtube, jawz go down failed\n");
        return 0;
    }

    //7, jaw open
    moveParam.pos = DP1_JAW_OPEN_POS;
    moveParam.dec_speed = 4000;
    moveParam.inc_speed = 4000;
    moveParam.speed = 4000;

    moveParam.sid = SID_DP1_JAW;

    actSuccess = uimMoveAct_multi(&moveParam,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp1_transtube, jaw open failed\n");
        return 0;
    }

    //8, jawz go up, jaw init
    move_param moveParamArr[2];
    moveParamArr[0].pos = 5000;
    moveParamArr[0].dec_speed = 120000;
    moveParamArr[0].inc_speed = 120000;
    moveParamArr[0].speed = 32000;

    moveParamArr[0].sid = SID_DP1_JAWZ;

    moveParamArr[1].pos = 0;
    moveParamArr[1].dec_speed = 4000;
    moveParamArr[1].inc_speed = 4000;
    moveParamArr[1].speed = 4000;

    moveParamArr[1].sid = SID_DP1_JAW;

    actSuccess = uimMoveAct_multi(moveParamArr,2,20000);

    if(actSuccess!=1)
    {
        printf("in dp1_transtube, jawz go up failed\n");
        return 0;
    }

    moveParamArr[0].pos = 0;
    moveParamArr[0].dec_speed = 10000;
    moveParamArr[0].inc_speed = 10000;
    moveParamArr[0].speed = 5000;

    moveParamArr[0].sid = SID_DP1_JAWZ;
    int moveNum = 1;

    if(needOpenDoor)
    {
        moveParamArr[1].pos = WASTE_DOOR_CLOSE_POS;
        moveParamArr[1].dec_speed = 160000;
        moveParamArr[1].inc_speed = 160000;
        moveParamArr[1].speed = 40000;

        moveParamArr[1].sid = SID_WASTE_DOOR;
        moveNum = 2;        
    }

    actSuccess = uimMoveAct_multi(moveParamArr,moveNum,30000);

    return actSuccess;
}

int dp1_pump_ctl(int isSuck, int volume)
{
    void * pstParam = NULL;
    int actSuccess = 0;

    suck_param suckParam = {
        .posPre = 0, // this should be change according to the ----
        .speedPre = 4500, // the speed go to previous position
        .air1Quan = 0, // the air quantity before suck liquid
        .speedDetect = 210,//20mm/s / 0.009525 = 209.973// the speed of detecting liquid face
        .threshold = 9, // the threshold of detecting
        .stepBelow = 10,// the step continue to go after detecting success
        .speedSuck = dp1SuckCtlParam[0].speedSuck,// the suck speed
        .quantity = volume, // the suck quantity
        .more = 0, // the reduntant quantity
        .posMax = 0, //the max pos to go if no liquid ----this should be changed.
        .posPost = 0, // the position after sucking finished--- this should equals to posPre 
        .speedPost = 105, // the speed to go to posPost,---equals to speedDetect
        .air2Quan = 0, // the air quantity after suck liquid    
        .spitQuan = 0, // spit back quantity
        .speedSuckAir1 = 50,//ul/s
        .delayAfterSuck = 1000, //ms
        .delayAfterSpit = 500, //ms
        .speedSuckAir2 = 50,//ul/s
        .spitSpeed = dp1SuckCtlParam[0].spitSpeed,//inc/s
    };

    tecan_liquid_param spitParam = {
        .posPre = 0,
        .posPost = 0,
        .posMax = 0,
        .quantity = volume, // the unit is uL
        .quanSpitAir1 = dp1SuckCtlParam[0].air2,
        .quanSuckBack = 5,
        .speed = (400*40),//400 ul/s * 40000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(20*z_steps_per_mm), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    int adp_opcode = TECAN_SUCK_SIMPLE;

    if(isSuck)
    {
        pstParam = &suckParam;
        adp_opcode = TECAN_SUCK_SIMPLE;
    }
    else
    {
        adp_opcode = TECAN_SPIT_SIMPLE;

        pstParam = &spitParam;

    } 

    actSuccess = adpCtl(pstParam,adp_opcode, 100000);

    return actSuccess;
}